{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import keras\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from keras.utils import np_utils\n",
    "from keras.models import Sequential,model_from_json\n",
    "from keras.utils.vis_utils import plot_model\n",
    "from keras.layers import SimpleRNN,Dense,Activation,Conv2D,MaxPool2D,Dropout,Flatten,MaxPooling2D,AveragePooling2D\n",
    "from keras.optimizers import SGD,Adam\n",
    "from keras.preprocessing.image import ImageDataGenerator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数据集的数量为： 35887\n"
     ]
    }
   ],
   "source": [
    "path = r\"D:\\AI\\fer2013\\fer2013.csv\"\n",
    "data = pd.read_csv(path)\n",
    "num_of_instances = len(data) #获取数据集的数量\n",
    "print(\"数据集的数量为：\",num_of_instances)\n",
    "\n",
    "pixels = data['pixels']\n",
    "emotions = data['emotion']\n",
    "usages = data['Usage']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_classes = 7   #表情的类别数目\n",
    "x_train,y_train,x_test,y_test = [],[],[],[]\n",
    "\n",
    "for emotion,img,usage in zip(emotions,pixels,usages):    \n",
    "    try: \n",
    "        emotion = keras.utils.to_categorical(emotion,num_classes)   # 独热向量编码\n",
    "        val = img.split(\" \")\n",
    "        pixels = np.array(val,'float32')\n",
    "        \n",
    "        if(usage == 'Training'):\n",
    "            x_train.append(pixels)\n",
    "            y_train.append(emotion)\n",
    "        elif(usage == 'PublicTest'):\n",
    "            x_test.append(pixels)\n",
    "            y_test.append(emotion)\n",
    "    except:\n",
    "        print(\"\",end=\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_train = np.array(x_train)\n",
    "y_train = np.array(y_train)\n",
    "x_train = x_train.reshape(-1,48,48,1)\n",
    "x_test = np.array(x_test)\n",
    "y_test = np.array(y_test)\n",
    "x_test = x_test.reshape(-1,48,48,1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 28709 samples, validate on 3589 samples\n",
      "Epoch 1/20\n",
      "28709/28709 [==============================] - 55s 2ms/step - loss: 1.8353 - acc: 0.2508 - val_loss: 1.8160 - val_acc: 0.2494\n",
      "Epoch 2/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.8133 - acc: 0.2512 - val_loss: 1.7982 - val_acc: 0.2494\n",
      "Epoch 3/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.7672 - acc: 0.2763 - val_loss: 1.6817 - val_acc: 0.3491\n",
      "Epoch 4/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.6548 - acc: 0.3495 - val_loss: 1.6036 - val_acc: 0.3856\n",
      "Epoch 5/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.5888 - acc: 0.3842 - val_loss: 1.5521 - val_acc: 0.4135\n",
      "Epoch 6/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.5422 - acc: 0.4041 - val_loss: 1.5150 - val_acc: 0.4260\n",
      "Epoch 7/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.5071 - acc: 0.4180 - val_loss: 1.5398 - val_acc: 0.4115\n",
      "Epoch 8/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.4744 - acc: 0.4335 - val_loss: 1.4667 - val_acc: 0.4439\n",
      "Epoch 9/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.4533 - acc: 0.4409 - val_loss: 1.4492 - val_acc: 0.4464\n",
      "Epoch 10/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.4227 - acc: 0.4542 - val_loss: 1.4449 - val_acc: 0.4522\n",
      "Epoch 11/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.3979 - acc: 0.4624 - val_loss: 1.4163 - val_acc: 0.4583\n",
      "Epoch 12/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.3804 - acc: 0.4713 - val_loss: 1.4152 - val_acc: 0.4614\n",
      "Epoch 13/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.3529 - acc: 0.4822 - val_loss: 1.3817 - val_acc: 0.4731\n",
      "Epoch 14/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.3316 - acc: 0.4923 - val_loss: 1.3719 - val_acc: 0.4773\n",
      "Epoch 15/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.3084 - acc: 0.5043 - val_loss: 1.3927 - val_acc: 0.4714\n",
      "Epoch 16/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.2930 - acc: 0.5084 - val_loss: 1.3630 - val_acc: 0.4806\n",
      "Epoch 17/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.2673 - acc: 0.5190 - val_loss: 1.3451 - val_acc: 0.4873\n",
      "Epoch 18/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.2523 - acc: 0.5243 - val_loss: 1.3411 - val_acc: 0.4937\n",
      "Epoch 19/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.2286 - acc: 0.5375 - val_loss: 1.3613 - val_acc: 0.4815\n",
      "Epoch 20/20\n",
      "28709/28709 [==============================] - 53s 2ms/step - loss: 1.2063 - acc: 0.5443 - val_loss: 1.3370 - val_acc: 0.4990\n",
      "Train loss: 1.1678798809217275\n",
      "Train accuracy: 56.23323696443349\n",
      "Test loss: 1.3370009116656139\n",
      "Test accuracy: 49.902479802708534\n"
     ]
    }
   ],
   "source": [
    "batch_size = 100\n",
    "epochs = 20\n",
    "\n",
    "model = Sequential()\n",
    "\n",
    "#layer_1\n",
    "model.add(Conv2D(32,(3,3),strides=(1,1),input_shape=(48,48,1),padding='same',data_format='channels_last',activation='relu',kernel_initializer='uniform'))\n",
    "model.add(Conv2D(32,(3,3),strides=(1,1),padding='same',data_format='channels_last',kernel_initializer='uniform',activation='relu'))\n",
    "model.add(MaxPooling2D((2,2)))\n",
    "\n",
    "    #layer_2\n",
    "model.add(Conv2D(64,(3,3),strides=(1,1),padding='same',data_format='channels_last',activation='relu',kernel_initializer='uniform'))\n",
    "model.add(Conv2D(64,(2,2),strides=(1,1),padding='same',data_format='channels_last',activation='relu',kernel_initializer='uniform'))\n",
    "model.add(MaxPooling2D((2,2)))\n",
    "\n",
    "    #layer_3\n",
    "model.add(Conv2D(128,(3,3),strides=(1,1),padding='same',data_format='channels_last',activation='relu'))\n",
    "model.add(Conv2D(128,(3,3),strides=(1,1),padding='same',data_format='channels_last',activation='relu'))\n",
    "model.add(Conv2D(128, (1, 1), strides=(1, 1), padding='same', data_format='channels_last', activation='relu'))\n",
    "model.add(MaxPooling2D((2,2)))\n",
    "    #layer_4\n",
    "model.add(Conv2D(256,(3,3),strides=(1,1),padding='same',data_format='channels_last',activation='relu'))\n",
    "model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', data_format='channels_last', activation='relu'))\n",
    "model.add(Conv2D(256, (1,1), strides=(1, 1), padding='same', data_format='channels_last', activation='relu'))\n",
    "model.add(MaxPooling2D((2,2)))\n",
    "\n",
    "    #layer_5\n",
    "model.add(Conv2D(512,(3,3),strides=(1,1),padding='same',data_format='channels_last',activation='relu'))\n",
    "model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', data_format='channels_last', activation='relu'))\n",
    "model.add(Conv2D(512, (1,1), strides=(1, 1), padding='same', data_format='channels_last', activation='relu'))\n",
    "model.add(MaxPooling2D((2,2)))\n",
    "\n",
    "model.add(Flatten())  #拉平\n",
    "model.add(Dense(1024,activation='relu'))\n",
    "model.add(Dropout(0.2))\n",
    "model.add(Dense(512,activation='relu'))\n",
    "model.add(Dropout(0.1))\n",
    "model.add(Dense(7,activation='softmax'))\n",
    "    \n",
    "#进行训练\n",
    "model.compile(loss = 'categorical_crossentropy',optimizer = Adam(lr=1e-5),metrics=['accuracy'])\n",
    "history = model.fit(x_train,y_train,batch_size=batch_size,epochs=epochs,validation_data=(x_test,y_test))\n",
    "\n",
    "\n",
    "train_score = model.evaluate(x_train, y_train, verbose=0)\n",
    "print('Train loss:', train_score[0])\n",
    "print('Train accuracy:', 100*train_score[1])\n",
    " \n",
    "test_score = model.evaluate(x_test, y_test, verbose=0)\n",
    "print('Test loss:', test_score[0])\n",
    "print('Test accuracy:', 100*test_score[1])\n",
    "\n",
    "model.save('my_model.h5')\n",
    "# model_json = model.to_json()\n",
    "# open('my_model_json.json', 'w').write(model_json)\n",
    "# model.save_weights('my_model_weights.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.metrics import confusion_matrix\n",
    "import itertools\n",
    "def plot_confusion_matrix(cm, classes,\n",
    "                          title='Confusion matrix',\n",
    "                          cmap=plt.cm.jet):\n",
    "    cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n",
    "    plt.imshow(cm, interpolation='nearest', cmap=cmap)\n",
    "    plt.title(title)\n",
    "    plt.colorbar()\n",
    "    tick_marks = np.arange(len(classes))\n",
    "    plt.xticks(tick_marks, classes, rotation=45)\n",
    "    plt.yticks(tick_marks, classes)\n",
    "    thresh = cm.max() / 2.\n",
    "    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):\n",
    "        plt.text(j, i, '{:.2f}'.format(cm[i, j]), horizontalalignment=\"center\",\n",
    "                 color=\"white\" if cm[i, j] > thresh else \"black\")\n",
    "    plt.tight_layout()\n",
    "    plt.ylabel('True label')\n",
    "    plt.xlabel('Predicted label')\n",
    "    plt.show()\n",
    "\n",
    "# 显示混淆矩阵\n",
    "def plot_confuse(model, x_val, y_val):\n",
    "    predictions = model.predict_classes(x_val)\n",
    "    truelabel = y_val.argmax(axis=-1)   # 将one-hot转化为label\n",
    "    conf_mat = confusion_matrix(y_true=truelabel, y_pred=predictions)\n",
    "    plt.figure()\n",
    "    plot_confusion_matrix(conf_mat, range(np.max(truelabel)+1))\n",
    "\n",
    "plot_confuse(model, x_test, y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
